//////////////////////////////////////////ok
#include"stdafx.h"

#include "bochs.h"



void IA32_CPU::SAHF(Ia32_Instruction_c *i)
{
	set_SF((AH & 0x80) >> 7);
	set_ZF((AH & 0x40) >> 6);
	set_AF((AH & 0x10) >> 4);
	set_CF(AH & 0x01);
	set_PF((AH & 0x04) >> 2);
}

void IA32_CPU::LAHF(Ia32_Instruction_c *i)
{
  AH = (get_SF() ? 0x80 : 0) |
       (get_ZF() ? 0x40 : 0) |
       (get_AF() ? 0x10 : 0) |
       (get_PF() ? 0x04 : 0) |
       (0x02) |
       (get_CF() ? 0x01 : 0);
}

void IA32_CPU::CLC(Ia32_Instruction_c *i)
{
  set_CF(0);
}

void IA32_CPU::STC(Ia32_Instruction_c *i)
{
  set_CF(1);
}

void IA32_CPU::CLI(Ia32_Instruction_c *i)
{
	Bit32u IOPL =  get_IOPL();
	Bit32u  cpl = CPL;

	if (IOPL < cpl) 
	{
        exception(IA32_GP_EXCEPTION, 0, 0);
        return;
    }

    clear_IF ();
}

void IA32_CPU::STI(Ia32_Instruction_c *i)
{
	Bit32u IOPL =  get_IOPL();
	Bit32u  cpl = CPL;

    if (cpl > IOPL) 
	{
      exception(IA32_GP_EXCEPTION, 0, 0);
      return;
    }

	if (! get_IF ()) 
	{
		assert_IF ();
		// enable interrupts
		inhibit_mask |= IA32_INHIBIT_INTERRUPTS;
		async_event = 1;
	}

}

void IA32_CPU::CLD(Ia32_Instruction_c *i)
{
	 clear_DF ();
}

void IA32_CPU::STD(Ia32_Instruction_c *i)
{
	 assert_DF ();
}

void IA32_CPU::CMC(Ia32_Instruction_c *i)
{
	 set_CF( !get_CF() );
}

void IA32_CPU::PUSHF_Fv(Ia32_Instruction_c *i)
{
		if (i->os32L()) 
		{
			push_32(read_eflags() & 0x00fcffff);
		}
		else
		{
			push_16(read_flags());
		}
}

void IA32_CPU::POPF_Fv(Ia32_Instruction_c *i)
{
		Bit32u changeMask = 0x004dd5;
		Bit32u flags32;

		if (i->os32L()) 
		{
			pop_32(&flags32);
			changeMask |= 0x240000; // ID,AC
			if (CPL==0)
				changeMask |= (3<<12); // IOPL

			if (CPL <=  get_IOPL())
				changeMask |= (1<<9); // IF
		}
		else
		{
			Bit16u flags16;
			pop_16(&flags16);
			flags32 = flags16;
		      
			if (CPL==0)
				changeMask |= (3<<12); // IOPL
			if (CPL <=  get_IOPL())
				changeMask |= (1<<9); // IF
		}

		flags32 &= ~( (1<<20) | (1<<19) ); // Clear VIP/VIF
		writeEFlags(flags32, changeMask);
}

void IA32_CPU::SALC(Ia32_Instruction_c *i)
{
	if ( get_CF() ) 
	{
		AL = 0xff;
	}
	else 
	{
		AL = 0x00;
	}
}
